
<!DOCTYPE html>

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />

    <title>Customizing Leo &#8212; Leo 6.7.2 documentation</title>
    <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
    <link rel="stylesheet" type="text/css" href="_static/classic.css" />
    <link rel="stylesheet" type="text/css" href="_static/custom.css" />
    
    <script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
    <script src="_static/jquery.js"></script>
    <script src="_static/underscore.js"></script>
    <script src="_static/_sphinx_javascript_frameworks_compat.js"></script>
    <script src="_static/doctools.js"></script>
    <script src="_static/sphinx_highlight.js"></script>
    
    <script src="_static/sidebar.js"></script>
    
    <link rel="index" title="Index" href="genindex.html" />
    <link rel="search" title="Search" href="search.html" />
    <link rel="next" title="Plugins" href="plugins.html" />
    <link rel="prev" title="Leo’s Markup Language" href="leomarkup.html" /> 
  </head><body>
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="plugins.html" title="Plugins"
             accesskey="N">next</a> |</li>
        <li class="right" >
          <a href="leomarkup.html" title="Leo’s Markup Language"
             accesskey="P">previous</a> |</li>
        <li class="nav-item nav-item-0"><a href="leo_toc.html">Leo 6.7.2 documentation</a> &#187;</li>
          <li class="nav-item nav-item-1"><a href="usersguide.html" accesskey="U">Leo’s Users Guide</a> &#187;</li>
        <li class="nav-item nav-item-this"><a href="">Customizing Leo</a></li> 
      </ul>
    </div>  

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body" role="main">
            
  <p>&lt;customizing.html#specifying-settings&gt;`_</p>
<section id="customizing-leo">
<h1>Customizing Leo<a class="headerlink" href="#customizing-leo" title="Permalink to this heading">¶</a></h1>
<p>This chapter discusses how to customize Leo using the plugins and other means. See <a class="reference internal" href="#using-settings">Using settings</a> for a description of how to change Leo’s settings.</p>
<div class="contents local topic" id="contents">
<p class="topic-title">Contents</p>
<ul class="simple">
<li><p><a class="reference internal" href="#using-settings" id="id1">Using settings</a></p>
<ul>
<li><p><a class="reference internal" href="#configuration-directories" id="id2">Configuration directories</a></p></li>
<li><p><a class="reference internal" href="#search-order-for-settings-files" id="id3">Search order for settings files</a></p></li>
<li><p><a class="reference internal" href="#safe-rules-for-local-settings" id="id4">Safe rules for local settings</a></p></li>
<li><p><a class="reference internal" href="#organizer-nodes" id="id5">Organizer nodes</a></p></li>
<li><p><a class="reference internal" href="#ignore-and-if-nodes" id="id6">&#64;ignore and &#64;if nodes</a></p></li>
<li><p><a class="reference internal" href="#simple-settings-nodes" id="id7">Simple settings nodes</a></p></li>
<li><p><a class="reference internal" href="#complex-settings-nodes" id="id8">Complex settings nodes</a></p>
<ul>
<li><p><a class="reference internal" href="#buttons" id="id9">&#64;buttons</a></p></li>
<li><p><a class="reference internal" href="#commands" id="id10">&#64;commands</a></p></li>
<li><p><a class="reference internal" href="#command-history" id="id11">&#64;command-history</a></p></li>
<li><p><a class="reference internal" href="#data" id="id12">&#64;data</a></p></li>
<li><p><a class="reference internal" href="#enabled-plugins" id="id13">&#64;enabled-plugins</a></p></li>
<li><p><a class="reference internal" href="#font" id="id14">&#64;font</a></p></li>
<li><p><a class="reference internal" href="#menuat" id="id15">&#64;menuat</a></p></li>
<li><p><a class="reference internal" href="#menus" id="id16">&#64;menus</a></p></li>
<li><p><a class="reference internal" href="#mode" id="id17">&#64;mode</a></p></li>
<li><p><a class="reference internal" href="#rclick" id="id18">&#64;rclick</a></p></li>
<li><p><a class="reference internal" href="#recentfiles" id="id19">&#64;recentfiles</a></p></li>
<li><p><a class="reference internal" href="#shortcuts" id="id20">&#64;shortcuts</a></p></li>
</ul>
</li>
</ul>
</li>
<li><p><a class="reference internal" href="#customizing-the-rst3-command" id="id21">Customizing the rst3 command</a></p></li>
<li><p><a class="reference internal" href="#theme-files" id="id22">Theme files</a></p></li>
<li><p><a class="reference internal" href="#input-modes" id="id23">Input modes</a></p></li>
<li><p><a class="reference internal" href="#ua-s-extensible-attribues-of-nodes" id="id24">uA’s: extensible attribues of nodes</a></p></li>
<li><p><a class="reference internal" href="#decluttering-headlines" id="id25">Decluttering headlines</a></p>
<ul>
<li><p><a class="reference internal" href="#examples" id="id26">Examples</a></p></li>
<li><p><a class="reference internal" href="#rule-replacement-lines" id="id27">Rule &amp; replacement lines</a></p></li>
<li><p><a class="reference internal" href="#style-lines" id="id28">Style lines</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#translating-leo-s-menus-and-messages" id="id29">Translating Leo’s menus and messages</a></p></li>
<li><p><a class="reference internal" href="#writing-new-importers" id="id30">Writing new importers</a></p></li>
</ul>
</div>
<section id="using-settings">
<h2><a class="toc-backref" href="#id1">Using settings</a><a class="headerlink" href="#using-settings" title="Permalink to this heading">¶</a></h2>
<p>Leo stores options in <strong>&#64;settings trees</strong>, outlines whose headline is &#64;settings. When opening a .leo file, Leo looks for &#64;settings trees not only in the outline being opened but also in various leoSettings.leo files. This scheme allows for the following kinds of settings:</p>
<ul class="simple">
<li><p>Per-installation or per-machine settings.</p></li>
<li><p>Per-user settings.</p></li>
<li><p>Per-folder settings.</p></li>
<li><p>Per-file settings.</p></li>
</ul>
<p>There are four kinds of settings files:</p>
<ol class="arabic simple">
<li><p><strong>Default settings files</strong>, named <strong>leoSettings.leo</strong>. Although they can be used in other ways, they typically contain default settings.</p></li>
<li><p><strong>Personal settings files</strong>, named <strong>myLeoSettings.leo</strong>. They provide a way of ensuring that your customized settings are not altered when updating Leo from git or while installing a new version of Leo. The myLeoSettings.leo acts much like Python’s site-customize.py file. myLeoSettings.leo will never be part of any Leo distribution, and it will never exist in Leo’s cvs repository. This solution is <em>much</em> better than trying to update leoSettings.leo with scripts.</p></li>
<li><p><strong>Machine settings files</strong>, named <strong>LeoSettings.leo</strong> (note the capital ‘L’), and appearing in a unique directory.</p></li>
<li><p><strong>Theme files</strong>. These are .leo files containing stylesheets and other appearance-related settings.</p></li>
</ol>
<p>The following sections describe the kinds of nodes in &#64;settings trees.</p>
<section id="configuration-directories">
<h3><a class="toc-backref" href="#id2">Configuration directories</a><a class="headerlink" href="#configuration-directories" title="Permalink to this heading">¶</a></h3>
<p>Settings files can be found in the following directories:</p>
<ul class="simple">
<li><p><strong>homeDir</strong>, the HOME/.leo directory. HOME is given by Python’s HOME environment variable, or by os.expanduser(‘~’) if no HOME environment variable exists.</p></li>
<li><p><strong>configDir</strong>, Leo’s configuration directory: leo/config.</p></li>
<li><p><strong>machineDir</strong>, the HOME/.leo/MACHINE directory. MACHINE is given by Python’s HOSTNAME environment variable, or by Python’s COMPUTERNAME environment variable if there is no HOSTNAME variable, or by the value returned by socket.gethostname() if neither environment variable exists.</p></li>
<li><p><strong>localDir</strong>, the directory containing the .leo file being loaded.</p></li>
</ul>
<p>Leo reports in the Log pane window on startup and when opening .leo files what HOME dir is used and which settings files are read.</p>
</section>
<section id="search-order-for-settings-files">
<h3><a class="toc-backref" href="#id3">Search order for settings files</a><a class="headerlink" href="#search-order-for-settings-files" title="Permalink to this heading">¶</a></h3>
<p>When reading a .leo file, Leo looks for settings in default settings files first, then settings in personal settings files, and finally settings in local settings files.  The exact search order is:</p>
<ol class="arabic simple">
<li><p>Default settings files:</p>
<ol class="loweralpha simple">
<li><p>configDir/leoSettings.leo</p></li>
<li><p>homeDir/leoSettings.leo</p></li>
<li><p>localDir/leoSettings.leo</p></li>
</ol>
</li>
<li><p>Personal settings files:</p>
<ol class="loweralpha simple">
<li><p>configDir/myLeoSettings.leo</p></li>
<li><p>homeDir/myLeoSettings.leo</p></li>
<li><p>homeDir/&lt;machine-name&gt;LeoSettings.leo (note capitalization)</p></li>
<li><p>localDir/myLeoSettings.leo</p></li>
</ol>
</li>
<li><p>Local settings files: the file being loaded.</p></li>
</ol>
<p>Settings that appear later in this list override settings that appear earlier in this list.  This happens on a setting-by-setting basis, <em>not</em> on a file-by-file basis.  In other words, each individual setting overrides only the <em>corresponding</em> setting in previously-read files.  Reading a setting file does <em>not</em> reset all previous settings. Note that the same file might appear several times in the search list. Leo detects such duplicate file names and only loads each settings file once. Leo remembers all the settings in settings files and does not reread those settings when reading another .leo file.</p>
<p><strong>Caution</strong>: This search order offers almost too much flexibility. This can be confusing, even for power users. It’s important to choose the “simplest configuration scheme that could possibly work”.  Something like:</p>
<ul class="simple">
<li><p>Use a single leoSettings.leo file for installation-wide defaults.</p></li>
<li><p>Use a single myLeoSettings.leo files for personal defaults.</p></li>
<li><p>Use local settings sparingly.</p></li>
</ul>
<p><strong>Important</strong>: it is good style to limit settings placed in myLeoSettings.leo to those settings that differ from default settings.</p>
</section>
<section id="safe-rules-for-local-settings">
<h3><a class="toc-backref" href="#id4">Safe rules for local settings</a><a class="headerlink" href="#safe-rules-for-local-settings" title="Permalink to this heading">¶</a></h3>
<p>You should use special care when placing default or personal settings files in <strong>local</strong> directories, that is, directories other than homeDir, configDir or machineDir. In particular, the value of localDir can change when Leo reads additional files. This can result in Leo finding new default and personal settings files. The values of these newly-read settings files will, as always, override any previously-read settings.</p>
<p>Let us say that a setting is <strong>volatile</strong> if it is different from a default setting. Let us say that settings file A.leo <strong>covers</strong> settings file if B.leo if all volatile settings in B.leo occur in A.leo. With these definitions, the <strong>safe rule</strong> for placing settings files in local directories is:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Settings</span> <span class="n">files</span> <span class="ow">in</span> <span class="n">local</span> <span class="n">directories</span> <span class="n">should</span>
<span class="n">cover</span> <span class="nb">all</span> <span class="n">other</span> <span class="n">settings</span> <span class="n">files</span><span class="o">.</span>
</pre></div>
</div>
<p>Following this rule will ensure that the per-directory defaults specified in the local settings file will take precedence over all previously-read default and personal settings files. Ignore this principle at your peril.</p>
</section>
<section id="organizer-nodes">
<h3><a class="toc-backref" href="#id5">Organizer nodes</a><a class="headerlink" href="#organizer-nodes" title="Permalink to this heading">¶</a></h3>
<p>Organizer nodes have headlines that do no start with &#64;. Organizer nodes may be inserted freely without changing the meaning of an &#64;setting tree.</p>
</section>
<section id="ignore-and-if-nodes">
<h3><a class="toc-backref" href="#id6">&#64;ignore and &#64;if nodes</a><a class="headerlink" href="#ignore-and-if-nodes" title="Permalink to this heading">¶</a></h3>
<p>Leo ignores any subtree of an &#64;settings tree whose headline starts with &#64;ignore.</p>
<p>You can use several other kinds of nodes to cause Leo to ignore parts of  an &#64;settings tree:</p>
<ul>
<li><p>&#64;if <em>expression</em></p>
<p>A node whose headline starts with &#64;if <em>expression</em> acts like an organizer node if the expression evaluates to True, otherwise acts like an &#64;ignore node. If the expression is empty the body text should contain a script that will be evaluated (in an empty context).</p>
</li>
<li><p>&#64;ifplatform <em>platform-name</em></p>
<p>Same as &#64;if sys.platform == “platform-name”: except that it isn’t necessary to import sys.</p>
</li>
<li><p>&#64;ifhostname <em>hostA,!hostB</em></p>
<p>Evaluates to True if and only if: h=g.computeMachineName(); h==hostA and h!=hostB. The “!” version allows matching to every machine name except the given one to allow differing settings on only a few machines.</p>
</li>
</ul>
</section>
<section id="simple-settings-nodes">
<h3><a class="toc-backref" href="#id7">Simple settings nodes</a><a class="headerlink" href="#simple-settings-nodes" title="Permalink to this heading">¶</a></h3>
<p>Simple settings nodes have headlines of the form <code class="docutils literal notranslate"><span class="pre">&#64;&lt;type&gt;</span> <span class="pre">name</span> <span class="pre">=</span> <span class="pre">val</span></code>.
These settings set the value of name to val, with the indicated type:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">&lt;</span><span class="nb">type</span><span class="o">&gt;</span>          <span class="n">Valid</span> <span class="n">values</span>
<span class="o">------</span>          <span class="o">------------</span>
<span class="nd">@bool</span>           <span class="kc">True</span><span class="p">,</span> <span class="kc">False</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span>
<span class="nd">@color</span>          <span class="n">A</span> <span class="n">Qt</span> <span class="n">color</span> <span class="n">name</span> <span class="ow">or</span> <span class="n">value</span><span class="p">,</span> <span class="n">such</span> <span class="k">as</span> <span class="s1">&#39;red&#39;</span> <span class="ow">or</span> <span class="s1">&#39;xf2fddff&#39;</span>
                <span class="p">(</span><span class="n">without</span> <span class="n">the</span> <span class="n">quotes</span><span class="p">)</span>
<span class="nd">@directory</span>      <span class="n">A</span> <span class="n">path</span> <span class="n">to</span> <span class="n">a</span> <span class="n">directory</span>
<span class="nd">@float</span>          <span class="n">A</span> <span class="n">floating</span> <span class="n">point</span> <span class="n">number</span> <span class="n">of</span> <span class="n">the</span> <span class="n">form</span> <span class="n">nn</span><span class="o">.</span><span class="n">ff</span><span class="o">.</span>
<span class="nd">@int</span>            <span class="n">An</span> <span class="n">integer</span>
<span class="nd">@ints</span><span class="p">[</span><span class="nb">list</span><span class="p">]</span>     <span class="n">An</span> <span class="n">integer</span> <span class="p">(</span><span class="n">must</span> <span class="n">be</span> <span class="n">one</span> <span class="n">of</span> <span class="n">the</span> <span class="n">ints</span> <span class="ow">in</span> <span class="n">the</span> <span class="nb">list</span><span class="p">)</span><span class="o">.</span>
                <span class="n">Example</span><span class="p">:</span> <span class="nd">@ints</span> <span class="n">meaningOfLife</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">42</span><span class="p">,</span><span class="mi">666</span><span class="p">]</span><span class="o">=</span><span class="mi">42</span>
<span class="nd">@keys</span><span class="p">[</span><span class="n">name</span><span class="p">]</span>     <span class="n">Gives</span> <span class="n">a</span> <span class="n">name</span> <span class="n">to</span> <span class="n">a</span> <span class="nb">set</span> <span class="n">of</span> <span class="n">bindings</span><span class="o">.</span>
                <span class="p">(</span><span class="n">For</span> <span class="n">the</span> <span class="n">Check</span> <span class="n">Bindings</span> <span class="n">script</span> <span class="ow">in</span> <span class="n">leoSettings</span><span class="o">.</span><span class="n">leo</span><span class="o">.</span><span class="p">)</span>
<span class="nd">@path</span>           <span class="n">A</span> <span class="n">path</span> <span class="n">to</span> <span class="n">a</span> <span class="n">directory</span> <span class="ow">or</span> <span class="n">file</span>
<span class="nd">@ratio</span>          <span class="n">A</span> <span class="n">floating</span> <span class="n">point</span> <span class="n">number</span> <span class="n">between</span> <span class="mf">0.0</span> <span class="ow">and</span> <span class="mf">1.0</span><span class="p">,</span> <span class="n">inclusive</span><span class="o">.</span>
<span class="nd">@string</span>         <span class="n">A</span> <span class="n">string</span>
<span class="nd">@strings</span><span class="p">[</span><span class="nb">list</span><span class="p">]</span>  <span class="n">A</span> <span class="n">string</span> <span class="p">(</span><span class="n">must</span> <span class="n">be</span> <span class="n">one</span> <span class="n">of</span> <span class="n">the</span> <span class="n">strings</span> <span class="ow">in</span> <span class="n">the</span> <span class="nb">list</span><span class="p">)</span><span class="o">.</span>
                <span class="n">Example</span><span class="p">:</span> <span class="nd">@strings</span> <span class="n">tk_relief</span><span class="p">[</span><span class="s1">&#39;flat&#39;</span><span class="p">,</span><span class="s1">&#39;groove&#39;</span><span class="p">,</span><span class="s1">&#39;raised&#39;</span><span class="p">]</span><span class="o">=</span><span class="s1">&#39;groove&#39;</span>
</pre></div>
</div>
<p><strong>Note</strong>: For a list of Tk color specifiers see:</p>
<ul class="simple">
<li><p><a class="reference external" href="http://www.tcl.tk/man/tcl8.4/TkCmd/colors.htm">http://www.tcl.tk/man/tcl8.4/TkCmd/colors.htm</a></p></li>
<li><p><a class="reference external" href="http://www.tcl.tk/man/tcl8.4/TkLib/GetColor.htm">http://www.tcl.tk/man/tcl8.4/TkLib/GetColor.htm</a></p></li>
</ul>
<p><strong>Important</strong>: you can use the show-colors minibuffer command to guide you in making these settings.</p>
</section>
<section id="complex-settings-nodes">
<h3><a class="toc-backref" href="#id8">Complex settings nodes</a><a class="headerlink" href="#complex-settings-nodes" title="Permalink to this heading">¶</a></h3>
<p>Complex settings nodes have headlines of the form <code class="docutils literal notranslate"><span class="pre">&#64;&lt;type&gt;</span> <span class="pre">description</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">@&lt;</span><span class="nb">type</span><span class="o">&gt;</span>             <span class="n">Valid</span> <span class="n">values</span>
<span class="o">-------</span>             <span class="o">------------</span>
<span class="nd">@buttons</span>            <span class="n">Child</span> <span class="nd">@button</span> <span class="n">nodes</span> <span class="n">create</span> <span class="k">global</span> <span class="n">buttons</span><span class="o">.</span>
<span class="nd">@commands</span>           <span class="n">Child</span> <span class="nd">@command</span> <span class="n">nodes</span> <span class="n">create</span> <span class="k">global</span> <span class="n">buttons</span><span class="o">.</span>
<span class="nd">@command</span><span class="o">-</span><span class="n">history</span>    <span class="n">Body</span> <span class="ow">is</span> <span class="n">a</span> <span class="nb">list</span> <span class="n">of</span> <span class="n">commands</span> <span class="n">pre</span><span class="o">-</span><span class="n">loaded</span> <span class="n">into</span> <span class="n">history</span> <span class="nb">list</span><span class="o">.</span>
<span class="nd">@data</span>               <span class="n">Body</span> <span class="ow">is</span> <span class="n">a</span> <span class="nb">list</span> <span class="n">of</span> <span class="n">strings</span><span class="p">,</span> <span class="n">one</span> <span class="n">per</span> <span class="n">line</span><span class="o">.</span>
<span class="nd">@enabled</span><span class="o">-</span><span class="n">plugins</span>    <span class="n">Body</span> <span class="ow">is</span> <span class="n">a</span> <span class="nb">list</span> <span class="n">of</span> <span class="n">enabled</span> <span class="n">plugins</span><span class="o">.</span>
<span class="nd">@font</span>               <span class="n">Body</span> <span class="ow">is</span> <span class="n">a</span> <span class="n">font</span> <span class="n">description</span><span class="o">.</span>
<span class="nd">@menus</span>              <span class="n">Child</span> <span class="nd">@menu</span> <span class="ow">and</span> <span class="nd">@item</span> <span class="n">nodes</span> <span class="n">create</span> <span class="n">menus</span> <span class="ow">and</span> <span class="n">menu</span> <span class="n">items</span><span class="o">.</span>
<span class="nd">@menuat</span>             <span class="n">Child</span> <span class="nd">@menu</span> <span class="ow">and</span> <span class="nd">@item</span> <span class="n">nodes</span> <span class="n">modify</span> <span class="n">menu</span> <span class="n">trees</span>
                    <span class="n">created</span> <span class="n">by</span> \<span class="nd">@menus</span><span class="o">.</span>
<span class="nd">@mode</span> <span class="p">[</span><span class="n">name</span><span class="p">]</span>        <span class="n">Body</span> <span class="ow">is</span> <span class="n">a</span> <span class="nb">list</span> <span class="n">of</span> <span class="n">shortcut</span> <span class="n">specifiers</span><span class="o">.</span>
<span class="nd">@recentfiles</span>        <span class="n">Body</span> <span class="ow">is</span> <span class="n">a</span> <span class="nb">list</span> <span class="n">of</span> <span class="n">file</span> <span class="n">paths</span><span class="o">.</span>
<span class="nd">@shortcuts</span>          <span class="n">Body</span> <span class="ow">is</span> <span class="n">a</span> <span class="nb">list</span> <span class="n">of</span> <span class="n">shortcut</span> <span class="n">specifies</span><span class="o">.</span>
</pre></div>
</div>
<p>Complex nodes specify settings in their body text.
See the following sections for details.</p>
<section id="buttons">
<h4><a class="toc-backref" href="#id9">&#64;buttons</a><a class="headerlink" href="#buttons" title="Permalink to this heading">¶</a></h4>
<p>An &#64;buttons tree in a settings file defines global buttons that are created in the icon area of all .leo files. All &#64;button nodes in the &#64;commands tree create global buttons. All &#64;button nodes outside the commands tree create buttons local to the settings file.</p>
</section>
<section id="commands">
<h4><a class="toc-backref" href="#id10">&#64;commands</a><a class="headerlink" href="#commands" title="Permalink to this heading">¶</a></h4>
<p>An &#64;commands tree in a settings file defines global commands. All &#64;command nodes in the &#64;commands tree create global commands. All &#64;command nodes outside the commands tree create commands local to the settings file.</p>
</section>
<section id="command-history">
<h4><a class="toc-backref" href="#id11">&#64;command-history</a><a class="headerlink" href="#command-history" title="Permalink to this heading">¶</a></h4>
<p>The body text contains a list of commands, one per line, to be preloaded into Leo’s command history. You access command history using the up and down arrow keys in Leo’s minibuffer.</p>
</section>
<section id="data">
<h4><a class="toc-backref" href="#id12">&#64;data</a><a class="headerlink" href="#data" title="Permalink to this heading">¶</a></h4>
<p>The body text contains a list of strings, one per line. Lines starting with ‘#’ are ignored.</p>
</section>
<section id="enabled-plugins">
<h4><a class="toc-backref" href="#id13">&#64;enabled-plugins</a><a class="headerlink" href="#enabled-plugins" title="Permalink to this heading">¶</a></h4>
<p>The body text of the &#64;enabled plugins node contains a list of enabled plugins, one per line. Comment lines starting with ‘#’ are ignored. Leo loads plugins in the order they appear. <strong>Important</strong>: Leo handles &#64;enabled-plugins nodes a differently from other kinds of settings. To avoid confusion, <strong>please read the following carefully</strong>.</p>
<p>As always, Leo looks for &#64;enabled-plugins nodes in settings files in the order specified by <a class="reference internal" href="#search-order-for-settings-files">Search order for settings files</a>. Leo will enable all plugins found in the &#64;enabled-plugins node it finds <em>last</em> in the search order. Leo does <em>not</em> enable plugins found in any other &#64;enabled-plugins node. In particular, <strong>you can not specify a list of default plugins by placing that list in a settings file that appears early in the search list</strong>. Instead, the last &#64;enabled-plugins node found in the search list specifies all and <em>only</em> the plugins that will be enabled.</p>
<p>Let us distinguish two different situations. First, what Leo does when loading a file, say x.leo. Second, what Leo does when loading a second file, say y.leo, <em>from x.leo</em>. When loading the first .leo file, Leo enables plugins from the
&#64;enabled-plugins node it finds <em>last</em> in the search order. But after plugins
have <em>already</em> been loaded and enabled, there is no way to disable previously
loaded-and-enabled plugins. But local settings files can enable additional
plugins.</p>
<p>To avoid confusion, I highly recommend following another kind of safe rule. We say that an &#64;enabled-plugin node in file A.leo <strong>covers</strong> an &#64;enabled-plugin node in file B.leo if all plugins specified in B’s &#64;enabled-plugin node appear A’s &#64;enabled-plugin node. The safe rule for plugins is:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@enabled</span><span class="o">-</span><span class="n">plugin</span> <span class="n">nodes</span> <span class="ow">in</span> <span class="n">settings</span> <span class="n">files</span> <span class="ow">in</span> <span class="n">local</span> <span class="n">directories</span>
<span class="n">should</span> <span class="n">cover</span> <span class="nd">@enabled</span><span class="o">-</span><span class="n">plugins</span> <span class="n">nodes</span> <span class="ow">in</span> <span class="nb">all</span> <span class="n">other</span> <span class="n">settings</span> <span class="n">files</span><span class="o">.</span>
</pre></div>
</div>
</section>
<section id="font">
<h4><a class="toc-backref" href="#id14">&#64;font</a><a class="headerlink" href="#font" title="Permalink to this heading">¶</a></h4>
<p>The body text contains a list of settings for a font.  For example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">body_text_font_family</span> <span class="o">=</span> <span class="n">Courier</span> <span class="n">New</span>
<span class="n">body_text_font_size</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">body_text_font_slant</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">body_text_font_weight</span> <span class="o">=</span> <span class="kc">None</span>
</pre></div>
</div>
<p><strong>Important</strong>: you can use the show-fonts minibuffer command to guide you in making these settings.</p>
</section>
<section id="menuat">
<h4><a class="toc-backref" href="#id15">&#64;menuat</a><a class="headerlink" href="#menuat" title="Permalink to this heading">¶</a></h4>
<p>&#64;menuat modifies the menu tree created by &#64;menus. This allows settings in myLeoSettings.leo to change menus without copying the entire menu tree from leoSettings.leo. This ensures you don’t miss out when new things are added in the &#64;menus in leoSettings.leo, as you would if you replaced the &#64;menus in leoSettings.leo with one in myLeoSettings.leo.</p>
<p>&#64;menuat should occur in a &#64;settings tree, but not as a descendant of a &#64;menus tree. Its children are &#64;menu and &#64;item nodes as for the &#64;menu setting.</p>
<p>The &#64;menuat setting has 2-3 parameters in its head text]:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@menuat</span> <span class="o">*&lt;</span><span class="n">path</span><span class="o">&gt;*</span> <span class="o">*&lt;</span><span class="n">action</span><span class="o">&gt;*</span> <span class="o">*</span><span class="p">[</span><span class="n">clipboard</span><span class="p">]</span><span class="o">*</span>
</pre></div>
</div>
<p>The path argument specifies a <strong>target</strong> in the menu tree as defined by &#64;menus and modified by earlier &#64;menuat settings. The path takes the form:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">/</span><span class="n">entry1</span><span class="o">/</span><span class="n">entry2</span><span class="o">/</span><span class="n">entry3</span>
</pre></div>
</div>
<p>Each entry is the <strong>cleaned</strong> name of a menu or item. Cleaned names are a name with all text except a-z and 0-9 removed and upper case letters converted to lower case. For example, specify:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Outline</span><span class="o">-&gt;</span><span class="n">Move</span><span class="o">-&gt;</span><span class="n">Move</span> <span class="n">Down</span>
</pre></div>
</div>
<p>as:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">/</span><span class="n">outline</span><span class="o">/</span><span class="n">move</span><span class="o">/</span><span class="n">movedown</span>
</pre></div>
</div>
<p>The action argument specifies what the menu item does. There are 5 available actions:</p>
<ul class="simple">
<li><p><strong>before</strong>: Insert items and sub menus immediately before the target.</p></li>
<li><p><strong>after</strong>:  Insert items and sub menus immediately after the target.</p></li>
<li><p><strong>append</strong>: Append items and sub menus at the end of the target menu or item.</p></li>
<li><p><strong>cut</strong>:    Remove the target from the menu tree and save it to an internal clipboard.</p></li>
<li><p><strong>copy</strong>:   Copy the target to an internal clipboard. Descendants of the &#64;menuat setting are ignored.</p></li>
</ul>
<p>The cut and copy arguments ignore descendants of the &#64;menuat setting .</p>
<p>The optional clipboard argument modifies the action of the before, after, and append actions. By default these actions insert the menus and items supplied as descendants of the &#64;menuat setting. If you specify “clipboard” (without the quotes) as the source, the contents of the clipboard from a previous cut or copy action will be used instead.</p>
</section>
<section id="menus">
<h4><a class="toc-backref" href="#id16">&#64;menus</a><a class="headerlink" href="#menus" title="Permalink to this heading">¶</a></h4>
<p>Leo creates its menus from the &#64;menu, &#64;item and &#64;popup nodes in the &#64;menus tree. Within &#64;menus trees, &#64;menu nodes create menus and &#64;item nodes create menu items.</p>
<p>The menu name always follows &#64;menu. If the menu name is ‘Plugins’, Leo will create the Plugins menu and populate the menu by calling the ‘create-optional-menus’ hook. This creates the Plugins menu as usual. Nested &#64;menu nodes define submenus.</p>
<p>The command name follows &#64;item. If the body text of an &#64;item node exists, this body text is the menu name. Otherwise, the menu name is the command name. However, if the command name starts with a ‘*’, hyphens are removed from the menu name. Menu names and command names may contain a single ampersand (&amp;). If present, the following character is underlined in the name. If the command name in an &#64;item node is just a hyphen (-), the item represents a menu separator.</p>
<p>&#64;popup <em>&lt;widget-name&gt;</em> creates a popup menu for use by the contextmenu.py plugin. The children of this node should be &#64;menu and &#64;item nodes, used as with &#64;menus.</p>
</section>
<section id="mode">
<h4><a class="toc-backref" href="#id17">&#64;mode</a><a class="headerlink" href="#mode" title="Permalink to this heading">¶</a></h4>
<p>Leo allows you to specify input modes. You enter mode x with the enter-x-mode command. The purpose of a mode is to create different bindings for keys within a mode. Often plain keys are useful in input modes.</p>
<p>You can specify modes with &#64;mode nodes in leoSettings.leo. &#64;mode nodes work just like &#64;shortcuts nodes, but in addition they have the side effect of creating the enter-&lt;mode name&gt;-mode command.</p>
<p>The form of this node is:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@mode</span> <span class="o">*&lt;</span><span class="n">mode</span> <span class="n">name</span><span class="o">&gt;*</span>
</pre></div>
</div>
<p>The body text contains a list of shortcut specifiers. &#64;mode nodes work just like &#64;shortcuts nodes, but in addition they have the side effect of creating the enter-&lt;mode name&gt;-mode command.</p>
<p>Notes:</p>
<ul>
<li><p>You can exit any mode using the keyboard-quit (Control-g) command. This is the <strong>only</strong> binding that is automatically created in each mode. All other bindings must be specified in the &#64;mode node. In particular, the bindings specified in &#64;shortcuts nodes are <strong>not</strong> in effect in mode (again, except for the keyboard-quit binding).</p></li>
<li><p>Leo supports something akin to tab completion within modes: if you type a key that isn’t bound in a mode a ‘Mode’ tab will appear in the log pane. This tab shows all the keys that you can type and the commands to which they are bound. The mode-help command does the same thing.</p></li>
<li><p>&#64;shortcuts nodes specify the bindings for what might be called the ‘top-level’ mode. These are the bindings in effect when no internal state is present, for example, just after executing the keyboard-quit command.</p></li>
<li><p>The top_level_unbound_key_action setting determines what happens to unbound keys in the top-level mode. Leo ignores unbound keys in all other modes. The possibilities are ‘insert’, ‘replace’ and ‘ignore’.</p></li>
<li><p>The set-insert-mode, set-overwrite-mode and set-ignore-mode commands alter what happens to unbound keys in the top-level mode.</p></li>
<li><p>If the &#64;mode headline contains ::, everything following the :: is the mode prompt. For example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@mode</span> <span class="n">abc</span> <span class="p">::</span> <span class="n">xyz</span>
</pre></div>
</div>
</li>
</ul>
<p>Creates the enter-abc-mode command, but the prompt for the command is xyz.</p>
<p>With all these options it should be possible to emulate the keyboard behavior of any other editor.</p>
</section>
<section id="rclick">
<h4><a class="toc-backref" href="#id18">&#64;rclick</a><a class="headerlink" href="#rclick" title="Permalink to this heading">¶</a></h4>
<p>For each &#64;button node, Leo adds right-click menu items for:</p>
<ul class="simple">
<li><p>&#64;rclick nodes directly <em>following</em> the &#64;button.</p></li>
<li><p>&#64;rclick nodes that are <em>children</em> of the &#64;button node, provided that the
&#64;button node has no <code class="docutils literal notranslate"><span class="pre">&#64;others</span></code> directive.</p></li>
</ul>
<p><strong>Standard rclick items</strong>: Leo adds two standard right-click menu items for
each &#64;button node: <code class="docutils literal notranslate"><span class="pre">Remove</span> <span class="pre">Button</span></code> and <code class="docutils literal notranslate"><span class="pre">Goto</span> <span class="pre">Script</span></code>. Leo adds the
indicator text <strong>only</strong> to buttons that contain right-click menu items in
addition to these two standard right-click menu items.</p>
<p>The headline of the &#64;rclick node gives the menu title. The body contains a
Leo script to execute when the user selects the menu item.</p>
<p><strong>Related Setting</strong>:</p>
<p>&#64;string mod_scripting_subtext = ▼</p>
<p>This setting specifies <strong>indicator text</strong> that indicates that an &#64;button button has right-click menu items created by &#64;rclick nodes.</p>
<p>Unicode chars like ▼ ▾ and … are typical choices for this text.</p>
</section>
<section id="recentfiles">
<h4><a class="toc-backref" href="#id19">&#64;recentfiles</a><a class="headerlink" href="#recentfiles" title="Permalink to this heading">¶</a></h4>
<p>The body text contains a list of paths of recently opened files, one path per line. Leo writes the list of recent files to .leoRecentFiles.txt in Leo’s config directory, again one file per line.</p>
</section>
<section id="shortcuts">
<h4><a class="toc-backref" href="#id20">&#64;shortcuts</a><a class="headerlink" href="#shortcuts" title="Permalink to this heading">¶</a></h4>
<p>The body text contains a list of shortcut specifiers.</p>
</section>
</section>
</section>
<section id="customizing-the-rst3-command">
<h2><a class="toc-backref" href="#id21">Customizing the rst3 command</a><a class="headerlink" href="#customizing-the-rst3-command" title="Permalink to this heading">¶</a></h2>
<p>This section explains how to use <strong>user filters</strong> to alter the output of
the rst3 command.</p>
<p><strong>Background</strong></p>
<p>The rst3 command converts &#64;rst trees containing <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> (rST)
or <a class="reference external" href="http://sphinx-doc.org/">Sphinx</a> markup to an <strong>intermediate string</strong>. Depending on user
options, rst3 will:</p>
<ul class="simple">
<li><p>write the intermediate string to an <strong>intermediate file</strong>.</p></li>
<li><p>send the intermediate string to <a class="reference external" href="http://docutils.sourceforge.net">docutils</a> for conversion to HTML, PDF,
<a class="reference external" href="http://www.latex-project.org/">LaTeX</a>, etc.</p></li>
</ul>
<p><strong>User filters</strong></p>
<p>Plugins or scripts may define two functions: a <strong>headline filter</strong> and a
<strong>body filter</strong>:</p>
<ul>
<li><p>rst3 calls the body filter for all nodes except descendants of
<cite>&#64;rst-ignore</cite> or <cite>&#64;rst-ignore-tree</cite> nodes.</p></li>
<li><dl class="simple">
<dt>rst3 calls the headline filter for all nodes except:</dt><dd><ul class="simple">
<li><p><cite>rst-no-head</cite> nodes or</p></li>
<li><p>descendants of <cite>&#64;rst-ignore</cite> or <cite>&#64;rst-ignore-tree</cite> nodes.</p></li>
</ul>
</dd>
</dl>
</li>
<li><p>plugins or scripts register filters as follows:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">c</span><span class="o">.</span><span class="n">rstCommands</span><span class="o">.</span><span class="n">register_body_filter</span><span class="p">(</span><span class="n">body_filter</span><span class="p">)</span>
<span class="n">c</span><span class="o">.</span><span class="n">rstCommands</span><span class="o">.</span><span class="n">register_headline_filter</span><span class="p">(</span><span class="n">headline_filter</span><span class="p">)</span>
</pre></div>
</div>
</li>
<li><p>The signature of all filters is <cite>filter-name (c, p)</cite> where c and p are
defined as usual.</p></li>
</ul>
<p><strong>Example filters</strong></p>
<p>Do-nothing filters would be defined like this:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">body_filter</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">p</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">p</span><span class="o">.</span><span class="n">b</span>

<span class="k">def</span> <span class="nf">headline_filter</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">p</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">p</span><span class="o">.</span><span class="n">h</span>
</pre></div>
</div>
<p>The following filters would simulate the frequently-requested “half clone” feature.
That is, within any &#64;rst tree, the following filters would skip the children of all clones:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">has_cloned_parent</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">p</span><span class="p">):</span>
<span class="w">    </span><span class="sd">&quot;&quot;&quot;Return True if p has a cloned parent within the @rst tree.&quot;&quot;&quot;</span>
    <span class="n">root</span> <span class="o">=</span> <span class="n">c</span><span class="o">.</span><span class="n">rstCommands</span><span class="o">.</span><span class="n">root</span>  <span class="c1"># The @rst node.</span>
    <span class="n">p</span> <span class="o">=</span> <span class="n">p</span><span class="o">.</span><span class="n">parent</span><span class="p">()</span>
    <span class="k">while</span> <span class="n">p</span> <span class="ow">and</span> <span class="n">p</span> <span class="o">!=</span> <span class="n">root</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">isCloned</span><span class="p">():</span>
            <span class="k">return</span> <span class="kc">True</span>
        <span class="n">p</span><span class="o">.</span><span class="n">moveToParent</span><span class="p">()</span>
    <span class="k">return</span> <span class="kc">False</span>

<span class="k">def</span> <span class="nf">body_filter</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">p</span><span class="p">):</span>
    <span class="k">return</span> <span class="s1">&#39;&#39;</span> <span class="k">if</span> <span class="n">has_cloned_parent</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span> <span class="k">else</span> <span class="n">p</span><span class="o">.</span><span class="n">b</span>

<span class="k">def</span> <span class="nf">headline_filter</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">p</span><span class="p">):</span>
    <span class="k">return</span> <span class="s1">&#39;&#39;</span> <span class="k">if</span> <span class="n">has_cloned_parent</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span> <span class="k">else</span> <span class="n">p</span><span class="o">.</span><span class="n">h</span>
</pre></div>
</div>
<p>Folks, this might send a shiver down your spine. Both filters ignore all
descendants of clones in the &#64;rst tree. We have the effect of half clones,
with no changes to Leo’s core!</p>
<p>Note: has_cloned_parent stops the scan at the &#64;rst node itself, ensuring
that the rst3 command includes “top-level” clones themselves.</p>
<p>See leo/plugins/example_rst_filter.py for a complete example.</p>
<p><strong>Filters can do practically anything</strong></p>
<p>Filters can use the data in p.b, p.h, p.u, or p.gnx, but filters are not <em>limited</em> to the data in p. The has_cloned_parent filter shows that filters can access:</p>
<ul class="simple">
<li><p>Any ancestor or descendant of node p.</p></li>
<li><p>Any data accessible from c, that is, <em>all</em> the data in the outline, including cached data!</p></li>
</ul>
<p>Indeed, has_cloned_parent gets the current <cite>&#64;rst</cite> node using <cite>root = c.rstCommands.root</cite>.</p>
<p>Moreover, filters can define special conventions, including:</p>
<ul class="simple">
<li><p>Special-format comments embedded in p.b,</p></li>
<li><p>Special-purpose headlines.</p></li>
</ul>
<p><strong>Summary</strong></p>
<p>Plugins and scripts can define headline and body filters that alter the intermediate string.</p>
<p>The leo/plugins/example_rst_filter.py plugin shows how to set up plugins that define custom filters.</p>
<p>Filters have easy access to all data within the outline, including:</p>
<ul class="simple">
<li><p>c.rstCommands.root, the <cite>&#64;rst</cite> node containing p.</p></li>
<li><p>All ancestors or descendants of p.</p></li>
<li><p>All data contained <em>anywhere</em> in the outline.</p></li>
</ul>
<p>The example filters shown above simulate the often-requested “half clone” feature.</p>
</section>
<section id="theme-files">
<h2><a class="toc-backref" href="#id22">Theme files</a><a class="headerlink" href="#theme-files" title="Permalink to this heading">¶</a></h2>
<p>A <strong>theme</strong> file is a .leo file containing appearance-related settings.  The leo/themes folder contains several examples.</p>
<p>The open-theme-file command will show you the effect of a theme file without changing Leo in any way.</p>
<p>To enable a theme, put the following setting in myLeoSettings.leo:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@string</span> <span class="n">theme</span><span class="o">-</span><span class="n">name</span> <span class="o">=</span> <span class="o">&lt;</span><span class="n">name</span> <span class="n">of</span> <span class="n">theme</span> <span class="n">file</span><span class="o">&gt;</span>
</pre></div>
</div>
<p><strong>Important</strong>: When using themes, it’s best to disable all other theme-related settings in myLeoSettings.leo.</p>
<p>Leo looks for the named .leo file in the following order:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">~</span>  <span class="p">(</span><span class="n">The</span> <span class="n">users</span> <span class="n">home</span> <span class="n">directory</span><span class="p">)</span>
<span class="o">~/</span><span class="n">themes</span>
<span class="o">~/.</span><span class="n">leo</span>
<span class="o">~/.</span><span class="n">leo</span><span class="o">/</span><span class="n">themes</span>
<span class="n">leo</span><span class="o">/</span><span class="n">themes</span>
</pre></div>
</div>
<p>Theme files should contain three settings that describe the theme:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@bool</span> <span class="n">color_theme_is_dark</span> <span class="c1"># True for dark themes</span>
<span class="nd">@string</span> <span class="n">color_theme</span> <span class="o">=</span> <span class="n">name</span> <span class="c1"># Used to find icons</span>
<span class="nd">@string</span> <span class="n">theme_name</span> <span class="c1"># Used to find other graphics elements.</span>
</pre></div>
</div>
</section>
<section id="input-modes">
<h2><a class="toc-backref" href="#id23">Input modes</a><a class="headerlink" href="#input-modes" title="Permalink to this heading">¶</a></h2>
<p>Leo now allows you to specify input modes. You enter mode x with the enter-x-mode command. The purpose of a mode is to create different bindings for keys within a mode. Often plain keys are useful in input modes.</p>
<p>You can specify modes with &#64;mode nodes in leoSettings.leo. &#64;mode nodes work just like &#64;shortcuts nodes, but in addition they have the side effect of creating the enter-&lt;mode name&gt;-mode command.</p>
<p>Notes:</p>
<ul>
<li><p>You can exit any mode using the keyboard-quit (Control-g) command. This is the <strong>only</strong> binding that is automatically created in each mode. All other bindings must be specified in the &#64;mode node. In particular, the bindings specified in &#64;shortcuts nodes are <strong>not</strong> in effect in mode (again, except for the keyboard-quit binding).</p></li>
<li><p>Leo supports something akin to tab completion within modes: if you type a key that isn’t bound in a mode a ‘Mode’ tab will appear in the log pane. This tab shows all the keys that you can type and the commands to which they are bound. The mode-help command does the same thing.</p></li>
<li><p>&#64;shortcuts nodes specify the bindings for what might be called the ‘top-level’ mode. These are the bindings in effect when no internal state is present, for example, just after executing the keyboard-quit command.</p></li>
<li><p>The top_level_unbound_key_action setting determines what happens to unbound keys in the top-level mode. Leo ignores unbound keys in all other modes. The possibilities are ‘insert’, ‘replace’ and ‘ignore’.</p></li>
<li><p>The set-insert-mode, set-overwrite-mode and set-ignore-mode commands alter what happens to unbound keys in the top-level mode.</p></li>
<li><p>If the &#64;mode headline contains ::, everything following the :: is the mode prompt. For example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@mode</span> <span class="n">abc</span> <span class="p">::</span> <span class="n">xyz</span>
</pre></div>
</div>
</li>
</ul>
<p>Creates the enter-abc-mode command, but the prompt for the command is xyz.</p>
<p>With all these options it should be possible to emulate the keyboard behavior of any other editor.</p>
</section>
<section id="ua-s-extensible-attribues-of-nodes">
<h2><a class="toc-backref" href="#id24">uA’s: extensible attribues of nodes</a><a class="headerlink" href="#ua-s-extensible-attribues-of-nodes" title="Permalink to this heading">¶</a></h2>
<p id="index-0">Leo’s .leo file format is extensible. The basis for extending .leo files are the v.unknownAttributes ivars of vnodes, also know as <strong>user attributes</strong>, uA’s for short. Leo translates between uA’s and xml attributes in the corresponding &lt;v&gt; elements in .leo files. Plugins may also use v.tempAttributes ivars to hold temporary information that will <em>not</em> be written to the .leo file. These two ivars are called <strong>attribute ivars</strong>.</p>
<p>Attribute ivars must be Python dictionaries, whose keys are names of plugins and whose values are <em>other</em> dictionaries, called <strong>inner dictionaries</strong>, for exclusive use of each plugin.</p>
<p>The v.u Python property allows plugins to get and set v.unknownAttributes easily:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">d</span> <span class="o">=</span> <span class="n">v</span><span class="o">.</span><span class="n">u</span> <span class="c1"># gets uA (the outer dict) for v</span>
<span class="n">v</span><span class="o">.</span><span class="n">u</span> <span class="o">=</span> <span class="n">d</span> <span class="c1"># sets uA (the outer dict) for v</span>
</pre></div>
</div>
<p>For example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">plugin_name</span> <span class="o">=</span> <span class="s1">&#39;xyzzy&#39;</span>
<span class="n">d</span> <span class="o">=</span> <span class="n">v</span><span class="o">.</span><span class="n">u</span> <span class="c1"># Get the outer dict.</span>
<span class="n">inner_d</span> <span class="o">=</span> <span class="n">d</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">plugin_name</span><span class="p">,{})</span> <span class="c1"># Get the inner dict.</span>
<span class="n">inner_d</span> <span class="p">[</span><span class="s1">&#39;duration&#39;</span><span class="p">]</span><span class="o">=</span> <span class="mi">5</span>
<span class="n">inner_d</span> <span class="p">[</span><span class="s1">&#39;notes&#39;</span><span class="p">]</span> <span class="s2">&quot;This is a note.&quot;</span>
<span class="n">d</span> <span class="p">[</span><span class="n">plugin_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">inner_d</span>
<span class="n">v</span><span class="o">.</span><span class="n">u</span> <span class="o">=</span> <span class="n">d</span>
</pre></div>
</div>
<p>No corresponding Python properties exist for v.tempAttributes, so the corresponding example would be:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">plugin_name</span> <span class="o">=</span> <span class="s1">&#39;xyzzy&#39;</span>
<span class="c1"># Get the outer dict.</span>
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">v</span><span class="p">,</span><span class="s1">&#39;tempAttributes&#39;</span><span class="p">):</span> <span class="n">d</span> <span class="o">=</span> <span class="n">p</span><span class="o">.</span><span class="n">v</span><span class="o">.</span><span class="n">tempAttributes</span>
<span class="k">else</span><span class="p">:</span> <span class="n">d</span> <span class="o">=</span> <span class="p">{}</span>
<span class="n">inner_d</span> <span class="o">=</span> <span class="n">d</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">plugin_name</span><span class="p">,{})</span> <span class="c1"># Get the inner dict.</span>
<span class="n">inner_d</span> <span class="p">[</span><span class="s1">&#39;duration&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="mi">5</span>
<span class="n">inner_d</span> <span class="p">[</span><span class="s1">&#39;notes&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&quot;This is a note.&quot;</span>
<span class="n">d</span> <span class="p">[</span><span class="n">plugin_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">inner_d</span>
<span class="n">p</span><span class="o">.</span><span class="n">v</span><span class="o">.</span><span class="n">tempAttributes</span> <span class="o">=</span> <span class="n">d</span>
</pre></div>
</div>
<p><strong>Important</strong>: All members of inner dictionaries should be picklable: Leo uses Python’s Pickle module to encode all values in these dictionaries. Leo will discard any attributes that can not be pickled. This should not be a major problem to plugins. For example, instead of putting a tnode into these dictionaries, a plugin could put the tnode’s gnx (a string) in the dictionary.</p>
<p><strong>Note</strong>: Leo does <em>not</em> pickle members of inner dictionaries whose name (key) starts with str_. The values of such members should be a Python string. This convention allows strings to appear in .leo files in a more readable format.</p>
<p>Here is how Leo associates uA’s with &lt;v&gt; elements in .leo files:</p>
<ul class="simple">
<li><p><strong>Native xml attributes</strong> are the attributes of &lt;v&gt; elements that are known (treated specially) by Leo’s read/write code. The native attributes of &lt;v&gt; elements are a, t, vtag, tnodeList, marks, expanded and descendentTnodeUnknownAttributes. All other attributes of &lt;v&gt; and &lt;t&gt; elements are <strong>foreign xml attributes</strong>.</p></li>
<li><p>When reading a .leo file, Leo will create v.unknownAttributes ivars for any vnode whose corresponding &lt;v&gt; or &lt;t&gt; element contains a foreign xml attribute.</p></li>
<li><p>When writing a file, Leo will write foreign xml attributes in &lt;v&gt; elements if the corresponding vnode contains an unknownAttributes ivar.</p></li>
<li><p>Leo performs the usual xml escapes on these strings when reading or writing the unknownAttributes ivars.</p></li>
</ul>
</section>
<section id="decluttering-headlines">
<h2><a class="toc-backref" href="#id25">Decluttering headlines</a><a class="headerlink" href="#decluttering-headlines" title="Permalink to this heading">¶</a></h2>
<p><strong>Decluttering</strong> replaces controls custom formatting of headlines, including:</p>
<ul class="simple">
<li><p>Hiding or changing headline text,</p></li>
<li><p>Adding icons to headlines,</p></li>
<li><p>Changing the styling of headlines.</p></li>
</ul>
<p>Decluttering is <em>inactive</em> when you are editing a headline.</p>
<p>Decluttering is <em>completely optional</em>. To enable decluttering, use:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@bool</span> <span class="n">tree</span><span class="o">-</span><span class="n">declutter</span> <span class="o">=</span> <span class="kc">True</span>
</pre></div>
</div>
<p>Decluttering is controlled by <strong>decluttering rulesets</strong>.
You specify decluttering rulesets in the body text of:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@data</span> <span class="n">tree</span><span class="o">-</span><span class="n">declutter</span><span class="o">-</span><span class="n">patterns</span>
</pre></div>
</div>
<p>As usual with &#64;data nodes:</p>
<ul class="simple">
<li><p>Blank lines and lines starting with ‘#’ are ignored.</p></li>
<li><p>You may organize the text of the &#64;data node using child nodes.</p></li>
</ul>
<p>Each ruleset consists of a list of lines:</p>
<ul class="simple">
<li><p>The first line is a <strong>rule line</strong>, containing a <strong>find pattern</strong>.</p></li>
<li><p>The second line is a <strong>replacement line</strong>.</p></li>
<li><p>The ruleset ends with zero or more <strong>style lines</strong>.</p></li>
</ul>
<p>Find patterns are <a class="reference external" href="https://docs.python.org/2/library/re.html">regular expressions</a>.
Decluttering affects only those headlines that match a rule pattern.</p>
<p>The following section shows some example rulesets. Later sections discuss decluttering commands, patterns and styles in more detail.</p>
<section id="examples">
<h3><a class="toc-backref" href="#id26">Examples</a><a class="headerlink" href="#examples" title="Permalink to this heading">¶</a></h3>
<p>Here are some examples of decluttering rulesets:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span># Hide org-mode tags and bold the headline.
RULE :([\w_@]+:)+\s*$
REPLACE-HEAD
WEIGHT Bold

# Replace @clean with an icon
RULE ^@clean (.*)
REPLACE \1
ICON file_icons/file_clean.png

# Show the last part of long filenames
RULE ^.{1,1000}([/\\])(.{25})
REPLACE …\1\2
</pre></div>
</div>
</section>
<section id="rule-replacement-lines">
<h3><a class="toc-backref" href="#id27">Rule &amp; replacement lines</a><a class="headerlink" href="#rule-replacement-lines" title="Permalink to this heading">¶</a></h3>
<p>All rulesets start with a <strong>rule line</strong> of the form:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">RULE</span> <span class="o">&lt;</span><span class="n">regular</span> <span class="n">expression</span><span class="o">&gt;</span>
</pre></div>
</div>
<p>The ruleset matches a headline if and only if the regular expression matches. Matches can start anywhere in the headline. Leo first attempts to a match using re.match. If that doesn’t work, Leo tries re.search.</p>
<p>A <strong>replacement line</strong> must follow the rule line. Here are the valid forms:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">REPLACE</span> <span class="o">&lt;</span><span class="n">substitution</span> <span class="n">expression</span><span class="o">&gt;</span>
<span class="n">REPLACE</span><span class="o">-</span><span class="n">HEAD</span>
<span class="n">REPLACE</span><span class="o">-</span><span class="n">TAIL</span>
<span class="n">REPLACE</span><span class="o">-</span><span class="n">REST</span>
</pre></div>
</div>
<ul>
<li><p>REPLACE replaces the headline by the value of the substitution expression.  For example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">REPLACE</span> \<span class="mi">1</span>
</pre></div>
</div>
<p>matches replaces the headline by the first matched regex group.</p>
</li>
<li><p>REPLACE-HEAD replaces replace the headline by the text that precedes the matched text.</p></li>
<li><p>REPLACE-TAIL replaces the headline by the text that follows the matched text.</p></li>
<li><p>REPLACE-REST replaces the headline by everything except the matched text.</p></li>
</ul>
</section>
<section id="style-lines">
<h3><a class="toc-backref" href="#id28">Style lines</a><a class="headerlink" href="#style-lines" title="Permalink to this heading">¶</a></h3>
<p>Leo applies style lines only if they appear in a ruleset that matches a headline. Style lines do the following…</p>
<p>Add an icon to the headline:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ICON</span> <span class="n">path</span><span class="o">/</span><span class="n">to</span><span class="o">/</span><span class="n">icon</span>
</pre></div>
</div>
<p>Set the background or foreground color to a color number or names:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">BG</span> <span class="c1">#FF8800</span>
<span class="n">FG</span> <span class="nd">@solarized</span><span class="o">-</span><span class="n">magenta</span>
</pre></div>
</div>
<p>Set the font to a given font name:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Font</span> <span class="n">Times</span>
</pre></div>
</div>
<p>Set the font size in pixels (PX) or points (PT):</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">PX</span> <span class="mi">40</span>
<span class="n">PT</span> <span class="mi">16</span>
</pre></div>
</div>
<p>Enable or disable italics:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ITALIC</span> <span class="mi">0</span>
<span class="n">ITALIC</span> <span class="mi">1</span>
</pre></div>
</div>
<p>Set the font weight to one of Light, Normal, DemiBold, Bold, Black:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">WEIGHT</span> <span class="n">DemiBold</span>
</pre></div>
</div>
</section>
</section>
<section id="translating-leo-s-menus-and-messages">
<h2><a class="toc-backref" href="#id29">Translating Leo’s menus and messages</a><a class="headerlink" href="#translating-leo-s-menus-and-messages" title="Permalink to this heading">¶</a></h2>
<p>It is easy to translate Leo’s menu strings: simply create an &#64;menus tree in leoSettings.leo or myLeoSettings.leo that contains the translated menu names.</p>
<p><strong>New in Leo 4.4.8</strong>: Leo now contains support for translating messages sent to Leo’s log:</p>
<ul class="simple">
<li><p>Rather than using an ‘_’ function to denote strings to be translated, Leo’s g.es and g.es_print functions translate “odd” (first, third, fifth) arguments, leaving “even” arguments untranslated. Keyword arguments, color, newline, etc. are never translated.</p></li>
<li><p>All calls to g.es and g.es_print in Leo’s core follow this convention.</p></li>
<li><p>g.translateString does the actual translation using Python’s <a class="reference external" href="http://docs.python.org/lib/module-gettext.html">gettext</a> module.</p></li>
<li><p>You can use the script in the node “&#64;button print g.es stats” in scripts.leo to create catalogs of all scripts that need to be translated. Such catalogs are used by Python’s gettext module. (This script was also used to check that the proper arguments to g.es and g.es_print were translated.)</p></li>
</ul>
</section>
<section id="writing-new-importers">
<h2><a class="toc-backref" href="#id30">Writing new importers</a><a class="headerlink" href="#writing-new-importers" title="Permalink to this heading">¶</a></h2>
<p>This section describes the process of creating an importer for a new language. There are a set of “importers” in leoImport.py, all based on the baseScannerClass class. You can define your own importer by creating a subclass. This shouldn’t be too difficult: baseScannerClass is supposed to do almost all the work. With luck, your subclass might be very simple, as with class cScanner.</p>
<p><strong>Important</strong> As I write this, I realize that I remember very little about the code, but I do remember its general organization and the process of creating a new importer. The following should be all you need to write any importer.</p>
<p>This base class has three main parts:</p>
<ol class="arabic simple">
<li><p>The “parser” that recognizes where nodes begin and end.</p></li>
<li><p>The “code generator” the actually creates the imported nodes.</p></li>
<li><p>Checking code that ensures that the imported code is equivalent to the original code.</p></li>
</ol>
<p>You should never have to change the code generators or the checking code. Confine your attention to the parser.</p>
<p>The parser thinks it is looking for classes, and within classes, method definitions.  Your job is to tell the parser how to do this. Let’s look at part of the ctor for baseScannerClass for clues:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># May be overridden in subclasses.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">anonymousClasses</span> <span class="o">=</span> <span class="p">[]</span> <span class="c1"># For Delphi Pascal interfaces.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">blockCommentDelim1</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">blockCommentDelim2</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">blockCommentDelim1_2</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">blockCommentDelim2_2</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">blockDelim1</span> <span class="o">=</span> <span class="s1">&#39;{&#39;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">blockDelim2</span> <span class="o">=</span> <span class="s1">&#39;}&#39;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">blockDelim2Cruft</span> <span class="o">=</span> <span class="p">[]</span> <span class="c1"># Stuff that can follow .blockDelim2.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">classTags</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;class&#39;</span><span class="p">,]</span> <span class="c1"># tags that start a tag.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">functionTags</span> <span class="o">=</span> <span class="p">[]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">hasClasses</span> <span class="o">=</span> <span class="kc">True</span>
<span class="bp">self</span><span class="o">.</span><span class="n">hasFunctions</span> <span class="o">=</span> <span class="kc">True</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lineCommentDelim</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lineCommentDelim2</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">outerBlockDelim1</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">outerBlockDelim2</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">outerBlockEndsDecls</span> <span class="o">=</span> <span class="kc">True</span>
<span class="bp">self</span><span class="o">.</span><span class="n">sigHeadExtraTokens</span> <span class="o">=</span> <span class="p">[]</span> <span class="c1"># Extra tokens valid in head of signature.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">sigFailTokens</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="c1"># A list of strings that abort a signature when seen in a tail.</span>
    <span class="c1"># For example, &#39;;&#39; and &#39;=&#39; in C.</span>
<span class="bp">self</span><span class="o">.</span><span class="n">strict</span> <span class="o">=</span> <span class="kc">False</span> <span class="c1"># True if leading whitespace is very significant.</span>
</pre></div>
</div>
<p>Yes, this looks like gibberish. I do <em>not</em> remember what all these things do in detail, although obviously the names mean something. What I <em>do</em> remember is that these ivars control the operation of the startsFunction and startsClass methods and their helpers (especially startsHelper) and the methods that call them, scan and scanHelper. Most of these methods have a trace var that will enable tracing during importing.</p>
<p>So the strategy is simple: study startsHelper in detail, set the ivars above to make startsHelper do what you want, and trace until things work as you want.</p>
<p>There is one more detail. Sometimes the ivars above are not sufficient to get the job done. In that case, subclasses will override various methods of the parser, but <em>not</em> the code generator. If indentation is important, you will want to look at the Python importer. Notice that it overrides skipCodeBlock, called by startsHelper.</p>
<p>That’s about it. It would be pointless to give you more details, because those details would lead you <em>away</em> from the process you need to follow. Having said that, feel free to ask further questions. I’ll be glad to answer them.</p>
</section>
</section>


            <div class="clearer"></div>
          </div>
        </div>
      </div>
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
            <p class="logo"><a href="leo_toc.html">
              <img class="logo" src="_static/LeoLogo.svg" alt="Logo"/>
            </a></p>
  <div>
    <h4>Previous topic</h4>
    <p class="topless"><a href="leomarkup.html"
                          title="previous chapter">Leo’s Markup Language</a></p>
  </div>
  <div>
    <h4>Next topic</h4>
    <p class="topless"><a href="plugins.html"
                          title="next chapter">Plugins</a></p>
  </div>
<div id="searchbox" style="display: none" role="search">
  <h3 id="searchlabel">Quick search</h3>
    <div class="searchformwrapper">
    <form class="search" action="search.html" method="get">
      <input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
      <input type="submit" value="Go" />
    </form>
    </div>
</div>
<script>document.getElementById('searchbox').style.display = "block"</script>
        </div>
<div id="sidebarbutton" title="Collapse sidebar">
<span>«</span>
</div>

      </div>
      <div class="clearer"></div>
    </div>
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="plugins.html" title="Plugins"
             >next</a> |</li>
        <li class="right" >
          <a href="leomarkup.html" title="Leo’s Markup Language"
             >previous</a> |</li>
        <li class="nav-item nav-item-0"><a href="leo_toc.html">Leo 6.7.2 documentation</a> &#187;</li>
          <li class="nav-item nav-item-1"><a href="usersguide.html" >Leo’s Users Guide</a> &#187;</li>
        <li class="nav-item nav-item-this"><a href="">Customizing Leo</a></li> 
      </ul>
    </div>
    <div class="footer" role="contentinfo">
        &#169; Copyright 1997-2023, Edward K. Ream.
      Last updated on February 28, 2023.
      Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 5.3.0.
    </div>
  </body>
</html>